package com.love.marriage.cloud.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.love.marriage.cloud.service.WechatWithdrawService;
import com.love.marriage.common.exceptions.SystemException;
import com.love.marriage.config.WeChatConfig;
import com.love.marriage.userCommissionWithdrawal.service.UserCommissionWithdrawalService;
import com.love.marriage.userCommissionWithdrawal.vo.UserCommissionWithdrawalVo;
import com.love.marriage.utils.AesUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.http.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
@RequiredArgsConstructor

public class WechatWithdrawServiceImpl implements WechatWithdrawService {

    private final WeChatConfig weChatConfig;

    private final RSAAutoCertificateConfig rsaAutoCertificateConfig;

    private final UserCommissionWithdrawalService userCommissionWithdrawalService;

    /**
     * 提现到微信零钱
     *
     * @param openId         用户OpenID
     * @param partnerTradeNo 商户订单号（唯一）
     * @param amount         提现金额（单位：分）
     * @param description    提现备注
     * @return 提现结果
     */
    @Override
    public Map<String, String> withdrawToWeChat(String openId, String partnerTradeNo, int amount, String description) throws WxPayException {
        Map<String, Object> map = new HashMap<>();
        map.put("appid", weChatConfig.getAppId());
        map.put("transfer_scene_id", "1000"); //发放场景
        map.put("out_bill_no", partnerTradeNo);
        map.put("openid", openId);
        map.put("transfer_amount", amount);
        map.put("transfer_remark", description);
        map.put("user_recv_perception", "现金奖励"); //用户感知
        map.put("notify_url", weChatConfig.getTransferNotifyUrl());
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> subMap = new HashMap<>(2);
        subMap.put("info_type", "活动名称");
        subMap.put("info_content", "佣金提现");
        Map<String, Object> subjectMap = new HashMap<>(2);
        subjectMap.put("info_type", "奖励说明");
        subjectMap.put("info_content", "推广佣金");
        list.add(subMap);
        list.add(subjectMap);
        map.put("transfer_scene_report_infos", list);
        OkHttpClient okHttpClient = new OkHttpClient();

        com.wechat.pay.java.core.http.HttpClient httpClient = new DefaultHttpClientBuilder().config(rsaAutoCertificateConfig).okHttpClient(okHttpClient).build();

        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Wechatpay-Serial", weChatConfig.getMchSerialNumber());

        String requestBody = JSONUtil.toJsonStr(map);

        JsonRequestBody build = new JsonRequestBody.Builder()
                .body(requestBody)
                .build();

        com.wechat.pay.java.core.http.HttpRequest executeSendGetHttpRequest =
                new HttpRequest.Builder()
                        .httpMethod(HttpMethod.POST)
                        .url(weChatConfig.getTransferUrl())
                        .headers(headers)
                        .body(build)
                        .build();
        String res;
        try {
            HttpResponse<Object> execute = httpClient.execute(executeSendGetHttpRequest, Object.class);
            ResponseBody body = execute.getBody();
            log.info("res ssssssssssssssssssssssssssssssssssss:{}", body);
           res = body.toString();
        } catch (Exception e) {
            log.error("发起微信转账失败：{}", e.getMessage());
            throw new SystemException("500", "发起微信转账失败，请联系管理员!");
        }
        Map<String, String> parseObject = JSONObject.parseObject(res, Map.class);
        Map<String, String> responseMap = JSONObject.parseObject(parseObject.get("body"), Map.class);
        log.info("微信转账响应" + responseMap);
        switch (responseMap.get("state")) {
            case "PROCESSING":
                throw new SystemException("500", "请联系管理员");
            case "WAIT_USER_CONFIRM":
            case "TRANSFERING":
                return responseMap;
            default:
                return responseMap;
        }
    }

    public Map<String, String> queryTransferByOutBillNo(String outBillNo) throws WxPayException {
        try {
            // 构建请求URL，替换路径参数
            String url = String.format(weChatConfig.getQueryTransferUrl() + "/%s", outBillNo);
            // 配置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
            OkHttpClient okHttpClient = new OkHttpClient();
            // 构建GET请求
            HttpRequest request = new HttpRequest.Builder()
                    .httpMethod(HttpMethod.GET)
                    .url(url)
                    .headers(headers)
                    .build();
            com.wechat.pay.java.core.http.HttpClient httpClient = new DefaultHttpClientBuilder().config(rsaAutoCertificateConfig).okHttpClient(okHttpClient).build();

            // 发送请求并获取响应
            HttpResponse<Object> execute = null;
            execute = httpClient.execute(request, Object.class);

            ResponseBody body = execute.getBody();
            log.info("res ssssssssssssssssssssssssssssssssssss:{}", body);
            String string = body.toString();
            Map<String, String> parseObject = JSONObject.parseObject(string, Map.class);
            Map<String, String> responseMap = JSONObject.parseObject(parseObject.get("body"), Map.class);
            log.info("查询微信转账响应" + responseMap);
            return responseMap;
        } catch (HttpException e) {
            // 处理HTTP异常
            throw new WxPayException("HTTP请求异常: " + e.getMessage(), e);
        } catch (ValidationException e) {
            // 处理签名验证失败
            throw new WxPayException("响应验证失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Boolean withdrawToWeChatNotify(String serial, String signature, String timestamp, String nonce, String requestBody) throws WxPayException {
        try {
            // 1. 验证签名
            boolean isValid = verifySignature(serial, signature, timestamp, nonce, requestBody);
            if (!isValid) {
                return false;
            }
            log.info("微信支付回调信息：{}", requestBody);
            // 2. 解析通知数据
            JSONObject notifyData = JSONObject.parseObject(requestBody);
            JSONObject resource = (JSONObject) notifyData.get("resource");
            log.info("resource:{},algorithm:{},associated_data:{},nonce:{}:{}", resource, resource.getString("algorithm"), resource.getString("associated_data"), resource.getString("nonce"), resource.getString("ciphertext"));
            AesUtil aesUtil = new AesUtil(weChatConfig.getApiv3().getBytes());
            String resInfo = aesUtil.decryptToString(resource.getString("associated_data").getBytes(), resource.getString("nonce").getBytes(), resource.getString("ciphertext"));
            log.info("解密后信息:{}", resInfo);
            JSONObject jsonObject = JSONObject.parseObject(resInfo);
            String outBillNo = jsonObject.getString("out_bill_no");
            String state = jsonObject.getString("state");
            String transferBillNo = jsonObject.getString("transfer_bill_no");
            String status = null;
            String failReason = null;
            // 3. 处理业务逻辑（如更新转账状态）
            if ("SUCCESS".equals(state)) {
                // 转账成功，更新数据库
                status = "COMPLETED";
            } else if ("CANCELLED".equals(state)) {
                // 转账失败，记录原因
                failReason = jsonObject.getString("fail_reason");
                status = "CANCEL";
            }
            UserCommissionWithdrawalVo query = new UserCommissionWithdrawalVo();
            query.setPartnerTradeNo(outBillNo);
            UserCommissionWithdrawalVo dbInfo = userCommissionWithdrawalService.queryUserCommissionWithdrawalInfo(query);
            if ("PENDING".equals(dbInfo.getStatus())) {
                userCommissionWithdrawalService.submitUserCommissionWithdrawal(dbInfo.getId(), status, failReason);
            }
            // 4. 返回成功响应（必须返回200状态码）
            return true;

        } catch (Exception e) {
            // 处理异常，返回失败（微信会重试）
            return false;
        }
    }

    /**
     * 验证微信签名
     */
    private boolean verifySignature(String serial, String signature, String timestamp,
                                    String nonce, String body) {
        String message = timestamp + "\n" + nonce + "\n" + body + "\n";
        // 使用微信平台证书公钥验证签名
        return rsaAutoCertificateConfig.createVerifier().verify(serial, message, signature);
    }

    public Map<String, String> cancelTransferByOutBillNo(String outBillNo) throws WxPayException {
        try {
            // 构建请求URL，替换路径参数
            String url = String.format("https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/%s/cancel", outBillNo);

            // 配置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
            headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());

            // 构建POST请求
            HttpRequest request = new HttpRequest.Builder()
                    .httpMethod(HttpMethod.POST)
                    .url(url)
                    .headers(headers)
                    .build();

            // 创建HttpClient（复用SDK配置）
            OkHttpClient okHttpClient = new OkHttpClient();
            HttpClient httpClient = new DefaultHttpClientBuilder()
                    .config(rsaAutoCertificateConfig)
                    .okHttpClient(okHttpClient)
                    .build();

            // 发送请求并获取响应
            HttpResponse<Object> response = httpClient.execute(request, Object.class);

            // 解析响应体
            ResponseBody body = response.getBody();
            String responseBody = body.toString();
            Map<String, String> resultMap = JSONObject.parseObject(responseBody, Map.class);

            log.info("微信转账撤销操作响应: {}", resultMap);
            return resultMap;
        } catch (HttpException e) {
            throw new WxPayException("HTTP请求异常: " + e.getMessage(), e);
        } catch (ValidationException e) {
            throw new WxPayException("签名验证失败: " + e.getMessage(), e);
        } catch (Exception e) {
            // 捕获其他潜在异常
            throw new WxPayException("操作异常: " + e.getMessage(), e);
        }
    }
}
